<template>
  <teleport to="body">
    <transition name="loading-fade">
      <div v-if="visible" class="global-loading-overlay" :class="{ 'loading-blur': blur }">
        <div class="global-loading-content">
          <a-spin 
            :size="size" 
            :spinning="true"
            :tip="tip"
          >
            <div class="loading-placeholder" />
          </a-spin>
          
          <!-- 自定义加载内容 -->
          <div v-if="$slots.default" class="loading-custom">
            <slot />
          </div>
          
          <!-- 进度条 -->
          <div v-if="showProgress && progress !== undefined" class="loading-progress">
            <a-progress 
              :percent="progress" 
              :status="progressStatus"
              :show-info="showProgressInfo"
              :stroke-color="progressColor"
            />
          </div>
          
          <!-- 描述文本 -->
          <div v-if="description" class="loading-description">
            {{ description }}
          </div>
        </div>
      </div>
    </transition>
  </teleport>
</template>

<script setup lang="ts">
import { computed } from 'vue'

interface GlobalLoadingProps {
  visible: boolean
  tip?: string
  description?: string
  size?: 'small' | 'default' | 'large'
  blur?: boolean
  showProgress?: boolean
  progress?: number
  progressStatus?: 'normal' | 'exception' | 'active' | 'success'
  progressColor?: string
  showProgressInfo?: boolean
}

const props = withDefaults(defineProps<GlobalLoadingProps>(), {
  tip: '加载中...',
  size: 'large',
  blur: true,
  showProgress: false,
  progressStatus: 'active',
  showProgressInfo: true,
})

// 阻止页面滚动
const preventScroll = (e: Event) => {
  e.preventDefault()
}

// 监听visible变化，控制页面滚动
const handleVisibleChange = (visible: boolean) => {
  if (visible) {
    document.body.style.overflow = 'hidden'
    document.addEventListener('touchmove', preventScroll, { passive: false })
  } else {
    document.body.style.overflow = ''
    document.removeEventListener('touchmove', preventScroll)
  }
}

// 监听props变化
watch(() => props.visible, handleVisibleChange)

// 组件卸载时清理
onUnmounted(() => {
  if (props.visible) {
    handleVisibleChange(false)
  }
})
</script>

<script lang="ts">
import { watch, onUnmounted } from 'vue'

export default {
  name: 'GlobalLoading'
}
</script>

<style scoped>
.global-loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.8);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
  backdrop-filter: blur(0px);
  transition: backdrop-filter 0.3s ease;
}

.global-loading-overlay.loading-blur {
  backdrop-filter: blur(4px);
}

.global-loading-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 32px;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.2);
  max-width: 400px;
  text-align: center;
}

.loading-placeholder {
  width: 60px;
  height: 60px;
}

.loading-custom {
  margin-top: 8px;
}

.loading-progress {
  width: 100%;
  margin-top: 8px;
}

.loading-description {
  color: rgba(0, 0, 0, 0.65);
  font-size: 14px;
  line-height: 1.5;
  margin-top: 8px;
}

/* 动画效果 */
.loading-fade-enter-active,
.loading-fade-leave-active {
  transition: all 0.3s ease;
}

.loading-fade-enter-from,
.loading-fade-leave-to {
  opacity: 0;
  backdrop-filter: blur(0px);
}

.loading-fade-enter-from .global-loading-content,
.loading-fade-leave-to .global-loading-content {
  transform: scale(0.9);
  opacity: 0;
}

/* 暗黑模式适配 */
[data-theme="dark"] .global-loading-overlay {
  background: rgba(0, 0, 0, 0.8);
}

[data-theme="dark"] .global-loading-content {
  background: rgba(20, 20, 20, 0.9);
  border-color: rgba(255, 255, 255, 0.1);
}

[data-theme="dark"] .loading-description {
  color: rgba(255, 255, 255, 0.65);
}

/* 响应式设计 */
@media (max-width: 768px) {
  .global-loading-content {
    margin: 16px;
    padding: 24px;
    max-width: calc(100vw - 32px);
  }
}
</style>